package is.ru.tgra;

import java.nio.FloatBuffer;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL11;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.BufferUtils;

public class Planet {
	
	Point3D pos;
	Vector3D u;
	Vector3D v;
	Vector3D n;
	
	private float orbitSpeed;
	private float planetSize;
	private String texture;
	private float radius;
	
	int stacks;
	int slices;
	FloatBuffer vertexBuffer;
	FloatBuffer normalBuffer;
	FloatBuffer texCoordBuffer;
	
	Texture tex;
	
	int vertexCount;
	
	/**
	 * @return the planetSize
	 */
	public float getPlanetSize() {
		return planetSize;
	}
	
	/**
	 * @return the texture
	 */
	public String getTexture() {
		return texture;
	}

	/**
	 * @param planetSize the planetSize to set
	 */
	public void setPlanetSize(float planetSize) {
		this.planetSize = planetSize;
	}

	/**
	 * @return the orbitSize
	 */
	public float getRadius() {
		return pos.x;
	}

	/**
	 * @param orbitSize the orbitSize to set
	 */
	public void setRadius(float radius) {
		this.radius = radius;
	}

	
	/**
	 * @return the orbitSpeed
	 */
	public float getOrbitSpeed() {
		return orbitSpeed;
	}

	/**
	 * @param orbitSpeed the orbitSpeed to set
	 */
	public void setOrbitSpeed(float orbitSpeed) {
		this.orbitSpeed = orbitSpeed;
	}

	/**
	 * @return the size
	 */
	public float getSize() {
		return planetSize;
	}
	
	public void setPos(float xx, float yy, float zz)
	{
		pos.x = xx;
		pos.y = yy;
		pos.z = zz;
	}
	
	public Planet(Point3D pPos, Point3D pCenter, Vector3D up, float pPlanetSize, float pRadius, float pOrbitSpeed, String pTexture, int i_stacks, int i_slices)
	{
		this.planetSize = pPlanetSize;
		this.radius = pRadius;
		this.orbitSpeed = pOrbitSpeed;
		this.texture = pTexture;
		pos = pPos;
		n = Vector3D.difference(pPos, pCenter);
		n.normalize();
		u = Vector3D.cross(up, n);
		u.normalize();
		v = Vector3D.cross(n, u);
		
		
		tex = new Texture(Gdx.files.internal("assets/textures/" + pTexture));
		
		stacks = i_stacks;
		slices = i_slices;
		vertexCount = 0;
		float[] array = new float[(stacks)*(slices+1)*6];
		float stackInterval = (float)Math.PI / (float)stacks;
		float sliceInterval = 2.0f*(float)Math.PI / (float)slices;
		
		float[] texArray = new float[(stacks)*(slices+1)*4];
		
		float stackAngle, sliceAngle;
		for(int stackCount = 0; stackCount < stacks; stackCount++)
		{
			stackAngle = stackCount * stackInterval;
			for(int sliceCount = 0; sliceCount < slices+1; sliceCount++)
			{
				sliceAngle = sliceCount * sliceInterval;
				array[vertexCount*3] = 	 (float)Math.sin(stackAngle) * (float)Math.cos(-sliceAngle);
				array[vertexCount*3 + 1] = (float)Math.cos(stackAngle);
				array[vertexCount*3 + 2] = (float)Math.sin(stackAngle) * (float)Math.sin(-sliceAngle);

				array[vertexCount*3 + 3] = (float)Math.sin(stackAngle + stackInterval) * (float)Math.cos(-sliceAngle);
				array[vertexCount*3 + 4] = (float)Math.cos(stackAngle + stackInterval);
				array[vertexCount*3 + 5] = (float)Math.sin(stackAngle + stackInterval) * (float)Math.sin(-sliceAngle);

				texArray[vertexCount*2] = (float)sliceCount / (float)slices;
				texArray[vertexCount*2 + 1] = (float)stackCount / (float)stacks;
				texArray[vertexCount*2 + 2] = (float)sliceCount / (float)slices;
				texArray[vertexCount*2 + 3] = (float)(stackCount+1) / (float)stacks;
				
				vertexCount += 2;
			}
		}
		vertexBuffer = BufferUtils.newFloatBuffer(vertexCount*3);
		vertexBuffer.put(array);
		vertexBuffer.rewind();
		normalBuffer = BufferUtils.newFloatBuffer(vertexCount*3);
		normalBuffer.put(array);
		normalBuffer.rewind();
		texCoordBuffer = BufferUtils.newFloatBuffer(vertexCount*2);
		texCoordBuffer.put(texArray);
		texCoordBuffer.rewind();
	}
	
	
	public void slide(float delU, float delV, float delN)
	{
		pos.add(Vector3D.sum(Vector3D.mult(delU, u), Vector3D.sum(Vector3D.mult(delV, v), Vector3D.mult(delN, n))));
	}

	public void yaw(float angle)
	{
		float c = (float) Math.cos(angle*Math.PI/180.0f);
		float s = (float) Math.sin(angle*Math.PI/180.0f);
		Vector3D t = u;
		u = Vector3D.sum(Vector3D.mult(c, t), Vector3D.mult(s, n));
		n = Vector3D.sum(Vector3D.mult(-s, t), Vector3D.mult(c, n));
	}
	
	public void draw()
	{
		
		Gdx.gl11.glShadeModel(GL11.GL_SMOOTH);
		Gdx.gl11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
		Gdx.gl11.glVertexPointer(3, GL11.GL_FLOAT, 0, vertexBuffer);
		Gdx.gl11.glNormalPointer(GL11.GL_FLOAT, 0, normalBuffer);

		Gdx.gl11.glEnable(GL11.GL_TEXTURE_2D);
		Gdx.gl11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

		Gdx.gl11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, texCoordBuffer);
		tex.bind();
		
		for(int i = 0; i < vertexCount; i += (slices+1)*2)
		{
			Gdx.gl11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, i, (slices+1)*2);
		}
		Gdx.gl11.glDisable(GL11.GL_TEXTURE_2D);
		Gdx.gl11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
		Gdx.gl11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
	}
	
	
}
